<template>
  <div class="dashbord">
    <div class="full" @click="dialogVisible = true">
      <el-icon size="28" color="#1ea6f8"><FullScreen /></el-icon>
    </div>
    <div class="header">
      <div class="title"></div>
    </div>
    <div class="main">
      <el-row :gutter="12">
        <el-col :lg="16" :md="24" :sm="24" :xl="16" :xs="24">
          <!-- 网络会话 -->
          <div class="network">
            <div class="network_header">
            <div class="left">
              <div class="network_bord"></div>
              <div class="network_title">网络会话</div>
            </div>
              <div>
                <el-date-picker
                  v-model="timeData"
                  type="datetimerange"
                  range-separator="至"
                  start-placeholder="起始时间"
                  end-placeholder="结束时间"
                  format="YYYY-MM-DD HH:mm:ss"
                  :teleported="false"
                  @change="handleDateChange"
                />
              </div>
            </div>
            <div ref="networkChart" class="network_content"></div>
          </div>
          <!-- 协议分布趋势 -->
          <div class="protocolTrend">
            <div class="protocolTrend_header">
              <div class="protocolTrend_bord"></div>
              <div class="protocolTrend_title">协议分布趋势</div>
            </div>
            <div ref="protocolTrendChart" class="protocolTrend_content"></div>
          </div>
        </el-col>
        <el-col :lg="8" :md="24" :sm="24" :xl="8" :xs="24">
          <!-- 协议类型分布 -->
          <div class="protocolType">
            <div class="protocolType_header">
              <div class="protocolType_bord"></div>
              <div class="protocolType_title">协议类型</div>
            </div>
            <div ref="protocolTypeChart" class="protocolType_content"></div>
          </div>
          <!-- 应用协议 -->
          <div class="applicationProtocol">
            <div class="applicationProtocol_header">
              <div class="applicationProtocol_bord"></div>
              <div class="applicationProtocol_title">应用协议分布</div>
            </div>
            <div ref="applicationProtocolChart" class="applicationProtocol_content"></div>
          </div>
        </el-col>
      </el-row>
    </div>
    <el-dialog v-model="dialogVisible" fullscreen draggable>
      <fullModal />
    </el-dialog>
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted } from 'vue'
import * as echarts from 'echarts'
const timeData = ref<[Date, Date]>([])
import fullModal from "./fullModal.vue";
import dayjs from 'dayjs'
import {
  getDashboardNetwork,
  getDashboardProtocolApp,
  getDashboardProtocolType,
  getDashboardProtocolBar
} from '@/api/business'

const protocolTypeChart = ref<HTMLElement | null>(null)
const applicationProtocolChart = ref<HTMLElement | null>(null)
const protocolTrendChart = ref<HTMLElement | null>(null)
const networkChart = ref<HTMLElement | null>(null)
const dialogVisible = ref(false);
onMounted(async () => {
  try {
    await fetchProtocolTypeData();
    await fetchApplicationProtocolData();
    await fetchProtocolTrendData();
    await fetchNetworkData();

    // 添加窗口大小变化监听
    window.addEventListener('resize', handleResize);
  } catch (error) {
    console.error("获取数据失败:", error);
  }
});
function handleResize() {
  if (protocolTypeChart.value) {
    const chart = echarts.getInstanceByDom(protocolTypeChart.value);
    if (chart) {
      chart.resize();
    }
  }
  if (applicationProtocolChart.value) {
    const chart = echarts.getInstanceByDom(applicationProtocolChart.value);
    if (chart) {
      chart.resize();
    }
  }
  if (protocolTrendChart.value) {
    const chart = echarts.getInstanceByDom(protocolTrendChart.value);
    if (chart) {
      chart.resize();
    }
  }
  if (networkChart.value) {
    const chart = echarts.getInstanceByDom(networkChart.value);
    if (chart) {
      chart.resize();
    }
  }
}
onUnmounted(() => {
  window.removeEventListener('resize', handleResize);
})
async function fetchProtocolTypeData() {
  try {
    const response = await getDashboardProtocolType()
    const protocolTypeData = response.map((item) => ({ value: item.count, name: item.protocol }))
    if (protocolTypeChart.value) {
      initChart(protocolTypeChart.value, {
        title: { left: 'center' },
        tooltip: { trigger: 'item' },
        legend: {
          orient: 'vertical',
          left: 'right',
          top: 'center',
          textStyle: { fontSize: 14, color: '#E8E8E8' }
        },
        series: [
          {
            name: '协议类型',
            type: 'pie',
            radius: ['20%', '70%'],
            label: { show: false },
            data: protocolTypeData,
            emphasis: {
              label: { show: true, fontSize: 40, fontWeight: 'bold' }
            },
            labelLine: { show: false }
          }
        ]
      })
    }
  } catch (error) {
    console.error('获取协议类型数据失败:', error)
  }
}

async function fetchApplicationProtocolData() {
  try {
    const now = dayjs()
    const threeMonthsAgo = now.subtract(3, 'month')
    const params = { startTime: threeMonthsAgo.format('YYYY-MM-DD HH:mm:ss'), endTime:now.format('YYYY-MM-DD HH:mm:ss') }
    const responseApp = await getDashboardProtocolApp(params)
    const applicationProtocolData = responseApp.map((item) => ({
      value: item.count,
      name: item.protocol
    }))
    if (applicationProtocolChart.value) {
      initChart(applicationProtocolChart.value, {
        title: { left: 'center' },
        tooltip: {
          trigger: 'item',
          formatter: '{a} <br/>{b}: {c} ({d}%)'
        },
        series: [
          {
            name: '应用协议',
            type: 'pie',
            radius: ['20%', '70%'],
            label: {
              show: true,
              formatter: '{b}({d}%)',
              position: 'inside',
              color: '#fff',
              fontSize: 12,
              rotate: 'radial'
            },
            labelLine: { show: false },
            data: applicationProtocolData,
            emphasis: {
              label: { show: true, fontSize: 14, fontWeight: 'bold' }
            }
          }
        ]
      })
    }
  } catch (error) {
    console.error('获取应用协议数据失败:', error)
  }
}

async function fetchProtocolTrendData() {
  try {
    const protocolTrendData = await getDashboardProtocolBar()
    if (protocolTrendChart.value) {
      // 提取协议名称作为图例
      const protocols = protocolTrendData.map(item => item.protocol)

      // 提取时间点作为 x 轴数据，并转换为年月日格式
      const timePoints = new Set<string>()
      const timeMap = new Map<string, string>() // 用于存储时间戳到日期字符串的映射

      protocolTrendData.forEach(item => {
        Object.keys(item.timeDistribution).forEach(time => {
          const formattedTime = dayjs(Number(time)).format('YYYY-MM-DD')
          timePoints.add(formattedTime)
          timeMap.set(time, formattedTime)
        })
      })
      const categories = Array.from(timePoints).sort((a, b) => new Date(a).getTime() - new Date(b).getTime())

      // 构建每个协议的时间分布数据
      const seriesData = protocols.map(protocol => {
        const data = categories.map(category => {
          const protocolData = protocolTrendData.find(item => item.protocol === protocol)
          if (protocolData) {
            // 找到所有匹配的原始时间戳
            const matchingTimes = Array.from(timeMap.entries()).filter(([time, formatted]) => formatted === category).map(([time]) => time)
            // 累加这些时间戳对应的值
            return matchingTimes.reduce((sum, time) => sum + (protocolData.timeDistribution[time] || 0), 0)
          }
          return 0
        })
        return {
          name: protocol,
          type: 'bar',
          stack: '总量',
          data: data,
          itemStyle: { color: getRandomColor() }
        }
      })

      initChart(protocolTrendChart.value, {
        title: { left: 'center' },
        grid: { x: 60, y: 40, x2: 25, y2: 25 },
        tooltip: {
          trigger: 'axis',
          axisPointer: { type: 'shadow' }
        },
        legend: {
          data: protocols,
          left: 'center',
          top: 'top',
          textStyle: { fontSize: 14, color: '#E8E8E8' }
        },
        xAxis: {
          type: 'category',
          data: categories,
          axisLabel: { color: '#E8E8E8' },
          axisLine: { lineStyle: { color: '#E8E8E8' } }
        },
        yAxis: {
          type: 'value',
          axisLabel: { color: '#E8E8E8' },
          axisLine: { lineStyle: { color: '#E8E8E8' } },
          splitLine: { lineStyle: { color: 'rgba(255, 255, 255, 0.1)' } }
        },
        series: seriesData
      })
    }
  } catch (error) {
    console.error('获取协议分布趋势数据失败:', error)
  }
}
async function handleDateChange(value: [Date, Date]){
    timeData.value = value
    await fetchNetworkData() 
}
async function fetchNetworkData() {
  try {
    const now = dayjs()
    const threeMonthsAgo = now.subtract(3, 'month')
    const params = { startTime: threeMonthsAgo.format('YYYY-MM-DD HH:mm:ss'), endTime:now.format('YYYY-MM-DD HH:mm:ss') }
    if (timeData.value.length>0) {
      params.startTime = dayjs(timeData.value[0]).format('YYYY-MM-DD HH:mm:ss')
      params.endTime = dayjs(timeData.value[1]).format('YYYY-MM-DD HH:mm:ss')
    }
    const responseNetwork = await getDashboardNetwork(params);
    const nodesSet = new Set<string>();
    const linksMap = new Map<string, { source: string; target: string; value: number }[]>();

    responseNetwork.forEach((item) => {
      nodesSet.add(item.sourceIp);
      nodesSet.add(item.descIp);
      const key = `${item.sourceIp}-${item.descIp}`;
      if (!linksMap.has(key)) {
        linksMap.set(key, []);
      }
      linksMap.get(key)!.push({ source: item.sourceIp, target: item.descIp, value: item.count });
    });

    // 合并相同source-target的链接并计算总值
    const links = Array.from(linksMap.entries()).map(([key, items]) => ({
      source: items[0].source,
      target: items[0].target,
      value: items.reduce((sum, item) => sum + item.value, 0)
    }));

    // 过滤形成链条的链接
    const hasOutEdges = new Set<string>();
    links.forEach(link => hasOutEdges.add(link.source));
    const filteredLinks = links.filter(link => !hasOutEdges.has(link.target));

    // 筛选前10条 value 最大的链接
    const top10Links = filteredLinks
      .sort((a, b) => b.value - a.value) // 按 value 降序排列
      .slice(0, 15); // 取前10条

    // 生成节点列表（仅包含出现在前10条链接中的节点）
    const nodesInLinks = new Set<string>();
    top10Links.forEach(link => {
      nodesInLinks.add(link.source);
      nodesInLinks.add(link.target);
    });
    const nodes = Array.from(nodesInLinks).map(name => ({ name }));

    if (networkChart.value) {
      initChart(networkChart.value, {
        tooltip: { trigger: 'item', triggerOn: 'mousemove' },
        series: [{
          type: 'sankey',
          left: 20,
          top: 20.0,
          right: 120,
          bottom: 20,
          data: nodes,
          links: top10Links,
          itemStyle: { borderWidth: 1, borderColor: '#aaa' },
          lineStyle: { color: 'source', curveness: 0.5 },
          label: { fontSize: 12, fontFamily: 'Arial', color: 'rgba(232, 232, 232, 0.8)'  }
        }]
      });
    }
  } catch (error) {
    console.error('获取网络会话数据失败:', error);
  }
}
function initChart(element: HTMLElement, option: echarts.EChartsOption) {
  const chart = echarts.init(element)
  chart.setOption(option)
}

function getRandomColor() {
  const letters = '0123456789ABCDEF'
  let color = '#'
  for (let i = 0; i < 6; i++) {
    color += letters[Math.floor(Math.random() * 16)]
  }
  return color
}
</script>

<style lang="scss" scoped>
.dashbord {
  background-image: url('../../../assets/imgs/business/bg.png');
  background-size: 100% 100%;
  background-repeat: no-repeat;
  width: 100%;
  overflow: hidden;
  height: 1130px;
  .full {
    position: relative;
    cursor: pointer;
    top: 2%;
    left: 1%;
    width: 40px;
    height: 40px;
  }
  .header {
    margin: 0 auto;
    width: 1111px;
    height: 137px;
    background-image: url('../../../assets/imgs/business/top.png');
    background-size: 100% 100%;
    background-repeat: no-repeat;

    .title {
      width: 488px;
      height: 70px;
      background-image: url('../../../assets/imgs/business/title.png');
      background-size: 100% 100%;
      background-repeat: no-repeat;
      margin: 0 auto;
    }
  }
  .main {
    margin: 0 38px;
    .network {
      .network_header {
        width: 100%;
        height: 44px;
        background-image: url(../../../assets/imgs/business/group_2.png);
        background-size: 100% 100%;
        background-repeat: no-repeat;
        display: flex;
        justify-content: space-between;
        align-items: center;
        .left{
          display: flex;
          align-items: center;
        }
        .network_bord {
          margin: 0 10px;
          width: 6px;
          height: 16px;
          background: linear-gradient(0deg, #2d93ff 0%, #11b5f2 99%);
        }
        .network_title {
          font-size: 18px;
          color: #ffffff;
        }
      }
      .network_content {
        width: 100%;
        height: 600px;
        background: rgba(13, 27, 53, 0.5);
        border-radius: 6px;
      }
    }
    .protocolTrend {
      margin-top: 20px;
      .protocolTrend_header {
        width: 100%;
        height: 44px;
        background-image: url(../../../assets/imgs/business/group_2.png);
        background-size: 100% 100%;
        background-repeat: no-repeat;
        display: flex;
        justify-content: start;
        align-items: center;
        .protocolTrend_bord {
          margin: 0 10px;
          width: 6px;
          height: 16px;
          background: linear-gradient(0deg, #2d93ff 0%, #11b5f2 99%);
        }
        .protocolTrend_title {
          font-size: 18px;
          color: #ffffff;
        }
      }
      .protocolTrend_content {
        width: 100%;
        height: 216px;
        background: rgba(13, 27, 53, 0.5);
        border-radius: 6px;
      }
    }
    .protocolType {
      .protocolType_header {
        width: 100%;
        height: 44px;
        background-image: url(../../../assets/imgs/business/group_1.png);
        background-size: 100% 100%;
        background-repeat: no-repeat;
        display: flex;
        justify-content: start;
        align-items: center;
        .protocolType_bord {
          margin: 0 10px;
          width: 6px;
          height: 16px;
          background: linear-gradient(0deg, #2d93ff 0%, #11b5f2 99%);
        }
        .protocolType_title {
          font-size: 18px;
          color: #ffffff;
        }
      }
      .protocolType_content {
        width: 100%;
        height: 400px;
        background: rgba(13, 27, 53, 0.5);
        border-radius: 6px;
      }
    }
    .applicationProtocol {
      margin-top: 20px;
      .applicationProtocol_header {
        width: 100%;
        height: 44px;
        background-image: url(../../../assets/imgs/business/group_1.png);
        background-size: 100% 100%;
        background-repeat: no-repeat;
        display: flex;
        justify-content: start;
        align-items: center;
        .applicationProtocol_bord {
          margin: 0 10px;
          width: 6px;
          height: 16px;
          background: linear-gradient(0deg, #2d93ff 0%, #11b5f2 99%);
        }
        .applicationProtocol_title {
          font-size: 18px;
          color: #ffffff;
        }
      }
      .applicationProtocol_content {
        width: 100%;
        height: 400px;
        background: rgba(13, 27, 53, 0.5);
        border-radius: 6px;
      }
    }
  }
}
</style>
